package com.yuanian.ecsplus.reflect;

import com.yuanian.ecsplus.context.ReflectContext;
import com.yuanian.ecsplus.exception.EcsPlusException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.*;

/**
 * 非持久化metaclass
 * @param <T>
 */
public class SimpleMetaClass<T> implements MetaClass {

    //实体类字节
    protected Class<T> clz;

    //类的构造函数
    protected Constructor<T> constructor;

    //实体类上所有字段
    protected List<EcsField> allField;

    protected Map<String, EcsField> fieldMap;

    public SimpleMetaClass(Class<T> clz) {
        this.clz = clz;
        try {
            //获取类的构造函数
            this.constructor = clz.getConstructor(null);
            //设置优化
            this.constructor.setAccessible(true);
        } catch (NoSuchMethodException e) {
            throw new EcsPlusException(e.getCause());
        }
        allField = new ArrayList<>();
        List<Field> allFieldTmp = new ArrayList<>();
        this.fieldMap = new HashMap<>();
        allFieldTmp.addAll(Arrays.asList(clz.getDeclaredFields()));
        //找到Base的字段
        if (clz.getSuperclass() != null) {
            allFieldTmp.addAll(Arrays.asList(clz.getSuperclass().getDeclaredFields()));
        }
        //遍历字段
        for (Field field : allFieldTmp) {
            //设置优化
            field.setAccessible(true);
            EcsField ecsField = new EcsField(field);
            this.fieldMap.put(field.getName(), ecsField);
            this.allField.add(ecsField);
        }
    }

    public Object newInstance() {
        if (this.constructor != null) {
            try {
                return this.constructor.newInstance();
            } catch (Exception e) {
                throw new EcsPlusException(e.getCause());
            }
        }
        return null;
    }

    @Override
    public Class getClazz() {
        return clz;
    }

    public List<EcsField> getAllFields() {
        return this.allField;
    }

    /**
     * 根据字段名获取字段的类型
     * @param fieldName
     * @return
     */
    public Class<?> getFieldType(String fieldName) {
        EcsField field = this.fieldMap.get(fieldName);
        if (field != null) {
            return field.getField().getType();
        } else {
            return null;
        }
    }

    @Override
    public Map toMap(Object obj) {
        if (obj == null) {
            return null;
        }
        Map map = new HashMap();
        for (EcsField field : getObject2MapFields()) {
            new ReflectContext(this, field, obj, map).handleObj2Map();
        }
        return map;
    }

    @Override
    public Object toEntity(Map data) {
        if (data == null || data.size() == 0) {
            return null;
        }
        //实体类字节码
        Object obj = newInstance();
        if (obj != null) {
            //复制属性
            copyProperty(obj, data);
            return obj;
        }
        return obj;
    }

    public void copyProperty(Object obj, Map data) {
        for (EcsField field : getMap2ObjectFields()) {
            new ReflectContext(this, field, obj, data).handleMap2Obj();
        }
    }

    @Override
    public List<EcsField> getObject2MapFields() {
        return getAllFields();
    }

    @Override
    public List<EcsField> getMap2ObjectFields() {
        return getAllFields();
    }

}
